﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using CPPEI.Coolzon.Common;
using System.IO;
using System.Xml;

namespace CPPEI.Coolzon.Metadata.ParserV1
{
    public class SolutionXmlParser : ISolutionXmlParser
    {
        private string SolutionFoldPath;
        private XmlDocument ReadDocument(string strPath)
        {
            XmlDocument xDoc = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            using (XmlReader reader = XmlReader.Create(strPath, settings))
            {
                xDoc.Load(reader);
            }
            return xDoc;
        }
        public Solution Load(string solutionFilePath)
        {
            XmlDocument xDoc = ReadDocument(solutionFilePath);
            SolutionFoldPath = solutionFilePath.Substring(0, solutionFilePath.LastIndexOf(@"\"));
            return Load(xDoc);
        }

        public Solution Load(XmlDocument xDoc)
        {
            if (xDoc == null) return null;
            try
            {
                XmlNode xSolution = xDoc.SelectSingleNode("Solution");
                if (xSolution == null) return null;

                Version rutimeVersion = null;
                Version version = null;
                Version.TryParse(xSolution.GetXAttributeValue("RuntimeVersion"), out rutimeVersion);
                Version.TryParse(xSolution.GetXAttributeValue("Version"), out version);

                Solution result = new Solution
                {
                    RuntimeVersion = rutimeVersion,
                    Version = version,
                    Name = xSolution.GetXAttributeValue("Name"),
                    Type = xSolution.GetXAttributeValue("Type"),
                    Caption = xSolution.GetXAttributeValue("Caption"),
                };
                XmlNode xDisplayFlow = xSolution.SelectSingleNode("Displayflow");
                if (xDisplayFlow != null)
                {
                    result.Displayflow = GetDisplayFlow(xDisplayFlow);
                }
                XmlNode xPropertyList = xSolution.SelectSingleNode("Property-List");
                if (xPropertyList != null)
                {
                    result.Properties = GetPropertyList(xPropertyList);
                }
                XmlNode xSceneList = xSolution.SelectSingleNode("Scene-List");
                if (xSceneList != null)
                {
                    result.Scenes = GetSceneList(xSceneList);
                }
                XmlNode xScriptEvents = xSolution.SelectSingleNode("ScriptEvent-List");
                if (xScriptEvents != null)
                {
                    result.ScriptEvents = GetScriptEventList(xScriptEvents);
                }
                return result;
            }
            catch (Exception ex)
            {
                Logger.Error("SolutionXmlParser,解析出错:" + ex.Message);
                return null;
            }
        }

        public void Save(XmlDocument xDoc, Solution solution)
        {
            XmlElement xPropertyList = xDoc.CreateElement("Property-List");
            XmlElement xSceneList = xDoc.CreateElement("Scene-List");
            XmlElement xDisplayflow = xDoc.CreateElement("Displayflow");
            SetProperties(xPropertyList, solution.Properties);
            SetScenes(xSceneList, solution.Scenes);
            SetDisplayflow(xDisplayflow, solution.Displayflow);

            XmlElement root = null;
            if (xDoc.FirstChild != null)
            {
                root = (XmlElement)xDoc.FirstChild;
                root.RemoveAll();
            }
            else
            {
                root = xDoc.CreateElement("Solution");
                xDoc.AppendChild(root);
            }
            XmlAttribute xName = xDoc.CreateAttribute("Name");
            xName.Value = solution.Name;

            XmlAttribute xCaption = xDoc.CreateAttribute("Caption");
            xCaption.Value = solution.Caption;

            XmlAttribute xVersion = xDoc.CreateAttribute("Version");
            xVersion.Value = solution.Version != null ? solution.Version.ToString() : string.Empty;

            XmlAttribute xRuntimeVersion = xDoc.CreateAttribute("RuntimeVersion");
            xVersion.Value = solution.RuntimeVersion != null ? solution.RuntimeVersion.ToString() : string.Empty;

            root.Attributes.Append(xName);
            root.Attributes.Append(xCaption);
            root.Attributes.Append(xVersion);
            root.Attributes.Append(xRuntimeVersion);
        }

        #region 设置XElement
        private void SetDisplayflow(XmlNode xDisplayflow, Displayflow displayflow)
        {
            if (displayflow == null) return;

            xDisplayflow.SetAttribute("BeginNode", displayflow.BeginNode);
            xDisplayflow.SetAttribute("IsRepeat", displayflow.IsRepeat ? bool.TrueString : bool.FalseString);
            xDisplayflow.SetAttribute("Interval", displayflow.Interval.ToString());

            for (int nodeIndex = 0; nodeIndex < displayflow.Nodes.Count; nodeIndex++)
            {
                XmlNode xDisplayflowNode = xDisplayflow.OwnerDocument.CreateElement("DisplayflowNode");

                xDisplayflowNode.SetAttribute("Name", displayflow.Nodes[nodeIndex].Name);
                xDisplayflowNode.SetAttribute("Caption", displayflow.Nodes[nodeIndex].Caption);
                xDisplayflowNode.SetAttribute("SceneName", displayflow.Nodes[nodeIndex].SceneName);
                xDisplayflowNode.SetAttribute("NextName", displayflow.Nodes[nodeIndex].NextName);

                XmlNode xParameterList = xDisplayflow.OwnerDocument.CreateElement("Parameter-List");
                List<Parameter> parameters = new List<Parameter>();
                for (int parameterIndex = 0;
                    parameterIndex < displayflow.Nodes[nodeIndex].SceneParameter.Count; parameterIndex++)
                {
                    parameters.Add(displayflow.Nodes[nodeIndex].SceneParameter.GetAt(parameterIndex));
                }

                SetParameters(xParameterList, parameters);
                xDisplayflow.AppendChild(xDisplayflowNode);
            }
        }
        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="properties"></param>
        /// <returns></returns>
        private void SetProperties(XmlNode xPropertyList, List<Property> properties)
        {
            if (properties == null) return;
            foreach (Property prop in properties)
            {
                XmlElement xProperty = xPropertyList.OwnerDocument.CreateElement("Property");
                if (!string.IsNullOrEmpty(prop.Name))
                {
                    xProperty.SetAttribute("Name", prop.Name);
                }
                if (!string.IsNullOrEmpty(prop.ValueString))
                {
                    xProperty.SetAttribute("Value", prop.ValueString);
                }
                if (prop.ValueNode != null)
                {
                    XmlElement xValueNode = xPropertyList.OwnerDocument.CreateElement("Property-Value");
                    SetValueNode(xValueNode, prop.ValueNode);
                    xProperty.AppendChild(xValueNode);
                }

                xPropertyList.AppendChild(xProperty);
            }
        }
        private void SetValueNode(XmlElement xValueNode, ValueNode valueNode)
        {
            if (valueNode == null) return;
            XmlElement xNode = xValueNode.OwnerDocument.CreateElement(valueNode.Name);
            xNode.Value = valueNode.Value == null ? string.Empty : valueNode.Value;

            if (valueNode.Attributes != null)
            {
                //给Property-Value添加属性
                foreach (KeyValuePair<string, string> kvp in valueNode.Attributes)
                {
                    xNode.SetAttribute(kvp.Key, kvp.Value);
                }
            }
            //添加Property-Value节点
            if (valueNode.ValueNodes != null)
            {
                foreach (ValueNode vN in valueNode.ValueNodes)
                {
                    SetValueNode(xNode, vN);
                }
            }
            xValueNode.AppendChild(xNode);
        }
        private void SetScenes(XmlNode xSceneList, List<Scene> scenes)
        {
            if (scenes == null) return;
            foreach (Scene scene in scenes)
            {
                XmlElement xScene = xSceneList.OwnerDocument.CreateElement("Scene");
                if (!string.IsNullOrEmpty(scene.Name))
                {
                    xScene.SetAttribute("Name", scene.Name);
                }
                if (!string.IsNullOrEmpty(scene.Caption))
                {
                    xScene.SetAttribute("Caption", scene.Caption);
                }
                xScene.SetAttribute("IsShowInNavigation", scene.IsShowInNavigation ? bool.TrueString : bool.FalseString);
                xScene.AddElement("Layout",
                    "Area-List",
                    "Property-List",
                    "Scene-List",
                    "Parameter-List",
                    "Comments-Link",
                    "Script-List",
                    "Template-List",
                    "ShorcutAction-List",
                    "CustomAction-List");

                SetAreas(xScene.SelectSingleNode("Area-List"), scene.Areas);
                SetProperties(xScene.SelectSingleNode("Property-List"), scene.Properties);
                SetScenes(xScene.SelectSingleNode("Scene-List"), scene.Scenes);
                SetParameters(xScene.SelectSingleNode("Parameter-List"), scene.Parameters);
                SetComments(xScene.SelectSingleNode("Comments-Link"), scene.CommentsLink);
                SetAction(xScene.SelectSingleNode("ShorcutAction-List"), scene.ShorcutActions);
                SetAction(xScene.SelectSingleNode("CustomAction-List"), scene.ShorcutActions);
                SetTemplateList(xScene.SelectSingleNode("Template-List"), scene.Templates);

                xSceneList.AppendChild(xScene);
            }
        }

        private void SetTemplateList(XmlNode xTemplateList, List<Template> list)
        {
            if (list == null) return;

            foreach (Template template in list)
            {
                XmlNode xTemplate = xTemplateList.OwnerDocument.CreateElement("Template");
                xTemplate.SetAttribute("Name", template.Name);

                XmlNode xPart = xTemplateList.OwnerDocument.CreateElement("Part");
                SetPart(xPart, template.Content);
                xTemplate.AppendChild(xPart);
            }
        }

        private void SetAction(XmlNode xActionList, List<CustomAction> list)
        {
            if (list == null) return;

            foreach (CustomAction action in list)
            {
                XmlNode xAction = xActionList.OwnerDocument.CreateElement("CustomAction");

                xActionList.SetAttribute("Caption", action.Caption ?? string.Empty);
                xActionList.SetAttribute("IsSys", action.IsSys ? bool.TrueString : bool.FalseString);

                foreach (CustomActionStep step in action.Steps)
                {
                    xActionList.AddElement("step", step.ScriptCode);
                }
                xActionList.AppendChild(xAction);
            }
        }
        private void SetParameters(XmlNode xParameters, List<Parameter> Parameters)
        {
            if (Parameters == null) return;

            foreach (Parameter parameter in Parameters)
            {
                XmlNode xParameter = xParameters.OwnerDocument.CreateElement("Parameter");
                xParameter.SetAttribute("Name", parameter.Name);
                xParameter.SetAttribute("Caption", parameter.Caption);
                xParameter.SetAttribute("Type", parameter.Type);
                xParameter.SetAttribute("ValueString", parameter.ValueString);
                xParameter.SetAttribute("ValueType", parameter.ValueType);
                xParameter.SetAttribute("Value", parameter.Value);

                xParameters.AppendChild(xParameter);
            }
        }
        /// <summary>
        /// 设置注释
        /// </summary>
        /// <param name="xComments"></param>
        /// <param name="CommentsLink"></param>
        private void SetComments(XmlNode xComments, CommentsLink CommentsLink)
        {
            if (CommentsLink == null) return;

            xComments.SetAttribute("Name", CommentsLink.Name);
        }

        /// <summary>
        /// 设置脚本
        /// </summary>
        /// <param name="xScripts"></param>
        /// <param name="Scripts"></param>
        private void SetScripts(XmlNode xScripts, List<Script> Scripts)
        {
            if (Scripts == null) return;

            foreach (Script script in Scripts)
            {
                XmlNode xScript = xScripts.AddElement("Script", script.Content);
                xScript.SetAttribute("Source", script.Source);

                xScripts.AppendChild(xScript);
            }
        }

        private void SetAreas(XmlNode xAreaList, List<Area> areas)
        {
            if (areas == null) return;
            foreach (Area area in areas)
            {
                XmlElement xArea = xAreaList.OwnerDocument.CreateElement("Area");
                if (!string.IsNullOrEmpty(area.Name))
                {
                    xArea.SetAttribute("Name", area.Name);
                }
                if (!string.IsNullOrEmpty(area.Caption))
                {
                    xArea.SetAttribute("Caption", area.Caption);
                }
                xArea.SetAttribute("IsAsContainer", area.IsAsContainer ? bool.TrueString : bool.FalseString);

                xArea.AddElement("Layout", "Area-List", "Property-List", "Part-List");

                SetAreas(xArea.SelectSingleNode("Area-List"), area.Areas);
                SetProperties(xArea.SelectSingleNode("Property-List"), area.Properties);
                SetParts(xArea.SelectSingleNode("Part-List"), area.Parts);

                xAreaList.AppendChild(xArea);
            }
        }

        private void SetParts(XmlNode xPartList, List<Part> parts)
        {
            if (parts == null) return;
            foreach (Part part in parts)
            {
                XmlNode xPart = xPartList.OwnerDocument.CreateElement("Part");
                SetPart(xPart, part);
                xPartList.AppendChild(xPart);
            }
        }
        private void SetPart(XmlNode xPart, Part part)
        {
            if (!string.IsNullOrEmpty(part.Name))
            {
                xPart.SetAttribute("Name", part.Name);
            }
            if (!string.IsNullOrEmpty(part.Caption))
            {
                xPart.SetAttribute("Caption", part.Caption);
            }

            if (!string.IsNullOrEmpty(part.Type))
            {
                xPart.SetAttribute("Type", part.Type);
            }
            xPart.AddElement("Layou", "Part-List", "Property-List", "Event-List");

            SetParts(xPart.SelectSingleNode("Part-List"), part.Parts);
            SetProperties(xPart.SelectSingleNode("Property-List"), part.Properties);
            SetEventList(xPart.SelectSingleNode("Event-List"), part.Events);
        }
        private void SetEventList(XmlNode xEventList, List<Event> events)
        {
            if (events == null) return;

            foreach (Event eventm in events)
            {
                XmlNode xEvent = xEventList.OwnerDocument.CreateElement("Event");
                if (!string.IsNullOrEmpty(eventm.Name))
                {
                    xEvent.SetAttribute("Name", eventm.Name);
                }
                if (!string.IsNullOrEmpty(eventm.Caption))
                {
                    xEvent.SetAttribute("Caption", eventm.Caption);
                }
                if (!string.IsNullOrEmpty(eventm.Source))
                {
                    xEvent.SetAttribute("Source", eventm.Source);
                }
                if (!string.IsNullOrEmpty(eventm.Action))
                {
                    xEvent.SetAttribute("Action", eventm.Action);
                }
                if (!string.IsNullOrEmpty(eventm.Condition))
                {
                    xEvent.SetAttribute("Condition", eventm.Condition);
                }
            }
        }
        #endregion

        #region 读取xml
        /// <summary>
        /// 获取场景
        /// </summary>
        /// <param name="xSceneList"></param>
        /// <returns></returns>
        private List<Scene> GetSceneList(XmlNode xScene)
        {
            List<Scene> scenes = new List<Scene>();
            if (xScene != null)
            {
                XmlNodeList xSceneList = xScene.SelectNodes("Scene");
                foreach (XmlNode xNode in xSceneList)
                {
                    scenes.Add(GetScene(xNode));
                }
                XmlNodeList xSceneRefList = xScene.SelectNodes("SceneRef");
                if (xSceneRefList != null)
                {
                    foreach (XmlNode xSceneRef in xSceneRefList)
                    {
                        string strPath = string.Format("{0}\\{1}", SolutionFoldPath, xSceneRef.GetXAttributeValue("Path"));
                        XmlDocument refDoc = ReadDocument(strPath);

                        scenes.Add(GetScene(refDoc.SelectSingleNode("Scene")));
                    }
                }
            }
            return scenes;
        }
        private Scene GetScene(XmlNode element)
        {
            return new Scene
                           {
                               Name = element.GetXAttributeValue("Name"),
                               Caption = element.GetXAttributeValue("Caption"),
                               IsShowInNavigation = (element.GetXAttributeValue("IsShowInNavigation") == null
                               || Convert.ToBoolean(element.GetXAttributeValue("IsShowInNavigation"))) ? true : false,
                               Scenes = GetSceneList(element.SelectSingleNode("Scene-List")),
                               Areas = GetAreaList(element.SelectSingleNode("Area-List")),
                               Properties = GetPropertyList(element.SelectSingleNode("Property-List")),
                               IsShowQueryPanel = Convert.ToBoolean(element.GetXAttributeValue("IsShowQueryPanel")) ? true : false,
                               Parameters = GetParamerters(element.SelectSingleNode("Parameter-List")),
                               Variables = GetVariables(element.SelectSingleNode("Variable-List")),
                               IsHorizontalLoopRender = Convert.ToBoolean(element.GetXAttributeValue("IsHorizontalLoopRender")),
                               CommentsLink = GetCommentsLink(element.SelectSingleNode("Comments-Link")),
                               Scripts = GetScriptList(element.SelectSingleNode("Script-List")),
                               ScriptEvents = GetScriptEventList(element.SelectSingleNode("ScriptEvent-List")),
                               IsAllowSwapArea = (element.GetXAttributeValue("IsAllowSwapArea") != null && Convert.ToBoolean(element.GetXAttributeValue("IsAllowSwapArea"))) ? true : false,
                               Templates = GetTemplates(element.SelectSingleNode("Template-List")),
                               ShorcutActions = GetCustomActions(element.SelectSingleNode("ShortcutAction-List")),
                               CustomActions = GetCustomActions(element.SelectSingleNode("CustomAction-List"))
                           };
        }

        private List<CustomAction> GetCustomActions(XmlNode xCustomActionList)
        {
            if (xCustomActionList != null)
            {
                List<CustomAction> customActions = new List<CustomAction>();
                foreach (XmlNode a in xCustomActionList.ChildNodes)
                {
                    CustomAction customAction = new CustomAction();
                    customAction.IsSys = Convert.ToBoolean(a.GetXAttributeValue("IsSYs"));
                    customAction.Caption = a.GetXAttributeValue("Caption");
                    customAction.Steps = GetGetCustomActionSteps(a);
                    customActions.Add(customAction);
                }
                return customActions;
            }
            return null;
        }

        private List<CustomActionStep> GetGetCustomActionSteps(XmlNode xCustomAction)
        {
            if (xCustomAction != null)
            {
                List<CustomActionStep> customActionSteps = new List<CustomActionStep>();
                foreach (XmlNode a in xCustomAction.SelectNodes("Step"))
                {
                    CustomActionStep customActionStep = new CustomActionStep();
                    customActionStep.ScriptCode = a.FirstChild == null ? string.Empty : a.FirstChild.InnerText.Trim();
                    customActionSteps.Add(customActionStep);
                }
                return customActionSteps;
            }
            return null;
        }

        private List<Template> GetTemplates(XmlNode xTemplateList)
        {
            if (xTemplateList != null)
            {
                List<Template> templates = new List<Template>();
                foreach (XmlNode a in xTemplateList.ChildNodes)
                {
                    Template template = new Template();
                    template.Name = a.GetXAttributeValue("Name");
                    template.Content = GetPart(a.SelectSingleNode("Part"));
                    templates.Add(template);
                }
                return templates;
            }
            return null;
        }
        /// <summary>
        /// 获取区域
        /// </summary>
        /// <param name="xAreaNode"></param>
        /// <returns></returns>
        private List<Area> GetAreaList(XmlNode xAreaNode)
        {
            if (xAreaNode != null)
            {
                List<Area> areas = new List<Area>();
                foreach (XmlNode a in xAreaNode.ChildNodes)
                {
                    try
                    {
                        switch (a.Name)
                        {
                            case "Area": areas.Add(GetArea(a)); break;
                            case "AreaRef":
                                string strPath = string.Format("{0}\\{1}", SolutionFoldPath, a.GetXAttributeValue("Path"));
                                XmlDocument xDoc = ReadDocument(strPath);

                                areas.Add(GetArea(xDoc.SelectSingleNode("Area")));
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Coolzon.Common.Logger.ErrorToTag("XmlParser", "AreaName:{0},ex:{1}", a.GetXAttributeValue("Name"), ex);
                    }
                }
                return areas;
            }
            return null;
        }
        private Area GetArea(XmlNode element)
        {
            bool tmpIsAsContainer;
            try
            {
                Area area = new Area
                            {
                                Name = element.GetXAttributeValue("Name"),
                                Caption = element.GetXAttributeValue("Caption"),
                                Areas = GetAreaList(element.SelectSingleNode("Area-List")),
                                Properties = GetPropertyList(element.SelectSingleNode("Property-List")),
                                Parts = GetPartList(element.SelectSingleNode("Part-List")),
                                ScriptEvents = GetScriptEventList(element.SelectSingleNode("ScriptEvent-List")),
                                IsAsContainer = (bool.TryParse(element.GetXAttributeValue("IsAsContainer"), out tmpIsAsContainer) ? tmpIsAsContainer : false),
                            };
                return area;
            }
            catch (Exception ex)
            {
                Coolzon.Common.Logger.ErrorToTag("XmlParser", "AreaName:{0},ex:{1}", element.GetXAttributeValue("Name"), ex);
            }
            return null;
        }

        /// <summary>
        /// 获取属性
        /// </summary>
        /// <param name="xPropertyList"></param>
        /// <returns></returns>
        private List<Property> GetPropertyList(XmlNode xPropertyList)
        {
            if (xPropertyList != null)
            {
                List<Property> propertyList = new List<Property>();
                XmlNodeList xNodePropertyList = xPropertyList.SelectNodes("Property");
                foreach (XmlNode a in xNodePropertyList)
                {
                    Property property = new Property
                    {
                        Name = a.GetXAttributeValue("Name"),
                        ValueString = a.GetXAttributeValue("Value"),
                        ValueNode = GetValueNode(a.SelectSingleNode("Property.Value"))
                    };
                    propertyList.Add(property);
                }
                return propertyList;
            }
            return null;
        }

        /// <summary>
        /// 获取组件
        /// </summary>
        /// <param name="xPart"></param>
        /// <returns></returns>
        private List<Part> GetPartList(XmlNode xPartList)
        {
            if (xPartList != null)
            {
                List<Part> partList = new List<Part>();
                foreach (XmlNode a in xPartList.SelectNodes("Part"))
                {
                    partList.Add(GetPart(a));
                }
                return partList;
            }
            return null;
        }
        private Part GetPart(XmlNode xPart)
        {
            Part part = new Part
                        {
                            Name = xPart.GetXAttributeValue("Name"),
                            Caption = xPart.GetXAttributeValue("Caption"),
                            Type = xPart.GetXAttributeValue("Type"),
                            Properties = GetPropertyList(xPart.SelectSingleNode("Property-List")),
                            Parts = GetPartList(xPart.SelectSingleNode("Part-List")),
                            Events = GetEventList(xPart.SelectSingleNode("Event-List")),
                            IsShowQueryPanel = Convert.ToBoolean(xPart.GetXAttributeValue("IsShowQueryPanel")) ? true : false,
                            ScriptEvents = GetScriptEventList(xPart.SelectSingleNode("ScriptEvent-List")),
                        };

            bool isPreload = false;
            if (bool.TryParse(xPart.GetXAttributeValue("IsPreload"), out isPreload))
            {
                isPreload = true;
            }
            part.IsPreload = isPreload;
            return part;
        }
        /// <summary>
        /// 获取参数
        /// </summary>
        /// <param name="xParameter"></param>
        /// <returns></returns>
        private List<Parameter> GetParamerters(XmlNode xParameter)
        {
            if (xParameter != null)
            {
                List<Parameter> parameterList = new List<Parameter>();
                XmlNodeList xParameterList = xParameter.SelectNodes("Parameter");
                foreach (XmlNode xNode in xParameterList)
                {
                    Parameter parameter = new Parameter
                    {
                        Caption = xNode.GetXAttributeValue("Caption"),
                        Name = xNode.GetXAttributeValue("Name"),
                        Type = xNode.GetXAttributeValue("Type"),
                        ValueString = xNode.GetXAttributeValue("ValueString"),
                        ValueType = xNode.GetXAttributeValue("ValueType"),
                        Value = xNode.GetXAttributeValue("Value")
                    };

                    parameterList.Add(parameter);
                }

                return parameterList;
            }
            return null;
        }

        /// <summary>
        /// 获取变量
        /// </summary>
        /// <param name="xVariable"></param>
        /// <returns></returns>
        private List<Variable> GetVariables(XmlNode xVariable)
        {
            if (xVariable != null)
            {
                List<Variable> variableList = new List<Variable>();
                XmlNodeList xVariableNodeList = xVariable.SelectNodes("Variable");
                foreach (XmlNode a in xVariableNodeList)
                {
                    Variable variable = new Variable
                    {
                        Caption = a.GetXAttributeValue("Caption"),
                        Name = a.GetXAttributeValue("Name"),
                        Type = a.GetXAttributeValue("Type"),
                        ValueString = a.GetXAttributeValue("ValueString"),
                        ValueType = a.GetXAttributeValue("ValueType")
                    };
                    variableList.Add(variable);
                }
                return variableList;
            }
            return null;
        }

        /// <summary>
        /// 获取备注信息
        /// </summary>
        /// <param name="xCommentsLink"></param>
        /// <returns></returns>
        private CommentsLink GetCommentsLink(XmlNode xCommentsLink)
        {
            if (xCommentsLink != null)
            {
                return new CommentsLink() { Name = xCommentsLink.GetXAttributeValue("Name") };
            }
            return null;
        }

        /// <summary>
        /// 获取脚本信息
        /// </summary>
        /// <param name="xScript"></param>
        /// <returns></returns>
        private List<Script> GetScriptList(XmlNode xScript)
        {
            if (xScript != null)
            {
                List<Script> scriptList = new List<Script>();
                foreach (XmlNode a in xScript.ChildNodes)
                {
                    Script script = new Script()
                    {
                        Source = a.GetXAttributeValue("Source"),
                        Content = a.InnerText.Trim(),
                    };
                    scriptList.Add(script);
                }
                return scriptList;
            }
            return null;
        }

        private Displayflow GetDisplayFlow(XmlNode xDisplayFlow)
        {
            if (xDisplayFlow != null)
            {
                Displayflow displayflow = new Displayflow
                {
                    BeginNode = xDisplayFlow.GetXAttributeValue("BeginNode"),
                    IsRepeat = Convert.ToBoolean(xDisplayFlow.GetXAttributeValue("IsRepeat")),
                    Interval = Convert.ToDouble(xDisplayFlow.GetXAttributeValue("SwitchInterval")),
                };
                GetDisplayFlowNodes(xDisplayFlow, displayflow.Nodes);

                return displayflow;
            }
            return null;
        }
        private void GetDisplayFlowNodes(XmlNode xDisplayflowNodes, DisplayflowNodeCollection nodes)
        {
            if (xDisplayflowNodes != null)
            {
                foreach (XmlNode element in xDisplayflowNodes.SelectNodes("DisplayflowNode"))
                {
                    DisplayflowNode displayflowNode = new DisplayflowNode
                    {
                        Name = element.GetXAttributeValue("Name"),
                        Caption = element.GetXAttributeValue("Caption"),
                        SceneName = element.GetXAttributeValue("SceneName"),
                        NextName = element.GetXAttributeValue("NextName")
                    };
                    nodes.Add(displayflowNode);

                    GetParameterCollection(element.SelectSingleNode("Parameter-List"), displayflowNode.SceneParameter);
                }
            }
        }
        private void GetParameterCollection(XmlNode xDisplayflowNode, ParameterCollection parameters)
        {
            if (xDisplayflowNode != null)
            {
                List<Parameter> parameterRange = GetParamerters(xDisplayflowNode);

                foreach (Parameter parameter in parameterRange)
                {
                    parameters.Add(parameter);
                }
            }
        }

        private ValueNode GetValueNode(XmlNode xPropertyValue)
        {
            if (xPropertyValue != null)
            {
                xPropertyValue = xPropertyValue.FirstChild;
                if (xPropertyValue == null) return null;
                if (xPropertyValue.Name == "#text")
                {
                    xPropertyValue = xPropertyValue.NextSibling;
                }
                return new ValueNode(xPropertyValue.Name)
                            {
                                Name = xPropertyValue.Name,
                                Attributes = GetValueNodeAttributes(xPropertyValue),
                                ValueNodes = GetValueNodes(xPropertyValue)
                            };
            }
            return null;
        }
        private Dictionary<string, string> GetValueNodeAttributes(XmlNode xValueNode)
        {
            if (xValueNode != null && xValueNode.Attributes != null)
            {
                Dictionary<string, string> dic = new Dictionary<string, string>();
                foreach (XmlAttribute a in xValueNode.Attributes)
                {
                    dic.Add(a.Name, a.Value);
                }
                return dic;
            }
            return null;
        }
        private List<ValueNode> GetValueNodes(XmlNode xNodeValue)
        {
            if (xNodeValue != null)
            {
                List<ValueNode> valueNodeList = new List<ValueNode>();

                foreach (XmlNode a in xNodeValue.ChildNodes)
                {
                    ValueNode valueNode = new ValueNode(a.Name)
                    {
                        Name = a.Name,
                        Attributes = GetValueNodeAttributes(a),
                        Value = a.FirstChild == null ? string.Empty : a.FirstChild.InnerText.ToString(),
                        ValueNodes = GetValueNodes(a)
                    };
                    valueNodeList.Add(valueNode);
                }

                return valueNodeList;
            }
            return null;
        }

        private List<Event> GetEventList(XmlNode xEventList)
        {
            if (xEventList != null)
            {
                List<Event> eventList = new List<Event>();
                XmlNodeList xEventNodeList = xEventList.SelectNodes("Event");
                foreach (XmlNode a in xEventList)
                {
                    Event _event = new Event
                    {
                        Name = a.GetXAttributeValue("Name"),
                        Caption = a.GetXAttributeValue("Caption"),
                        Source = a.GetXAttributeValue("Source"),
                        Action = a.GetXElementValue("Action"),
                        Condition = a.GetXElementValue("Condition")
                    };
                    eventList.Add(_event);
                }
                return eventList;
            }
            return null;
        }
        /// <summary>
        /// 获取脚本事件列表
        /// </summary>
        /// <param name="xScriptEventList"></param>
        /// <returns></returns>
        private List<ScriptEvent> GetScriptEventList(XmlNode xScriptEvent)
        {
            if (xScriptEvent != null)
            {
                List<ScriptEvent> scriptEvents = new List<ScriptEvent>();
                XmlNodeList xScriptEventList = xScriptEvent.SelectNodes("ScriptEvent");
                foreach (XmlNode a in xScriptEventList)
                {
                    ScriptEvent scriptEvent = new ScriptEvent
                    {
                        Source = a.GetXAttributeValue("Source"),
                        Script = a.GetXAttributeValue("Script")
                    };

                    scriptEvents.Add(scriptEvent);
                }

                return scriptEvents;
            }
            return null;
        }
        #endregion


        /// <summary>
        /// 获取用户自定义按钮列表
        /// </summary>
        /// <param name="customActionFile">Action文件路径</param>
        /// <returns></returns>
        public List<CustomAction> GetCustomActionList(string customActionFile)
        {
            if (!File.Exists(customActionFile)) return null;
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(customActionFile);

            return GetCustomActions(xDoc.FirstChild);
        }

        /// <summary>
        /// 保存用户自定义的按钮信息
        /// </summary>
        /// <param name="filePath">保存的文件路径</param>
        /// <param name="customActionList"></param>
        /// <returns></returns>
        public bool SaveCustomActionList(string filePath, List<CustomAction> customActionList)
        {
            XmlDocument xDoc = new XmlDocument();

            if (System.IO.File.Exists(filePath))
            {
                xDoc.Load(filePath);
            }
            else
            {
                XmlDeclaration dec = xDoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xDoc.AppendChild(dec);
            }
            XmlNode xActionList = xDoc.SelectSingleNode("CustomAction-List");
            if (xActionList == null)
            {
                xActionList = xDoc.CreateNode(XmlNodeType.Element, "CustomAction-List", null);
                xDoc.AppendChild(xActionList);
            }

            SetAction(xActionList, customActionList);
            if (xActionList.ChildNodes != null && xActionList.ChildNodes.Count > 0)
            {
                string fileDir = filePath.Substring(0, filePath.LastIndexOf("\\"));
                if (!System.IO.Directory.Exists(fileDir))
                {
                    System.IO.Directory.CreateDirectory(fileDir);
                }

                xDoc.Save(filePath);
                return true;
            }
            return false;
        }
    }
}
